MIDI Music
Volume Number: 10
Issue Number: 10
Column Tag: New Apple Technology
Related Info: Sound Manager
Making MIDI Music
Using QuickTime 2.0 to make some music of your own
By Glenn Andreas, Fridley, MN
Note: Source code files accompanying article are located on MacTech CD-ROM or
source code disks.
About The Author
Glenn Andreas - Glenn started Mac programming in the Fall of 84 when he conned
his boss into buying him a Lisa and the original IM. Since then, he’s written the game
Theldrow, worked for Palomar Software writing printer drivers, and done various
freelance programming jobs, including a sped up version of the Stylewriter driver
(which never shipped), and some work on the printing portions of Bedrock ( which
also never shipped). He’s currently working a “day job” which involves hacking the
BSD kernel, while trying to finish his latest game Chimera (which will hopefully ship
one day).
Editor’s Introduction
Glenn tried to use Apple docs to figure out how to generate MIDImusic with
QuickTime 2.0. He ran into the common insufficient documentation (what’s that error
number, again?) roadblock, and dove in to figure out how things really operate. In
doing so, he ran some risk of learning how to do things the wrong way, so we gave some
good folks at Apple a crack at his article. While calling the approach a bit “hackish”
because he defines his own headers, they say he pretty much got it right. While there
are easier ways to put MIDItunes into QuickTime movies and play them as background
music, this article shows you how to drive from the APIlevel. It’s rather like using
the Sound Manager with QuickTime.
Two caveats - the flags in TuneStop are not implemented (the article suggests
they are) and TuneResume doesn’t.
Be sure to check out the real documentation when it comes available, and enjoy
MusicTest in the meantime!
The Motivation
As I worked on my latest project, I wanted to have background music. I was
originally planning on writing some sort of “auto mixing my own sound buffers from
hell” sound manager hack, and while these are fun to write, it would take a great deal
of resources to get it correct. Then I heard that QuickTime 2.0 would include the
ability to play music, as music. “Sort of like MIDI” I heard. Call me a crazy, but I’d
rather just make a few component manager calls rather than spend months writing my
own music playing routines (besides having all my work done for me, QT 2.0 can play
the music through an external MIDI device as well for even better quality with almost
no system load). So, I got a beta of QT 2.0, and immediately dove into the “Macintosh
Music Architecture” document. This was rather like diving in the shallow end of the
pool. Given that the header code and the documentation didn’t synch all that well, and
assuming that the underlying code followed yet another convention, I did what any
resourceful programmer would do - I dropped into MacsBug.
Fortunately for me, MoviePlayer was able to correctly play some of the sample
music movies included on the beta CD. And, also fortunately for me, the whole music
architecture is build uses the component manager ( which, by the way for those who
have never really looked at it, is really cool). So I set a breakpoint at the beginning of
the “Tune Player Component”, and watched every call made by QuickTime as it played
music. And finally, after countless reboots, I was able to make my Mac play music
from my own programs.
At this point, I saw this as an opportunity for a little fortune and glory. Given
that the only existing document I had on how to play music was inaccurate, I figured
that I would write this article explaining just what it will take for you to easily add
background music to your current or future project. Note that this article is in no
way official documentation, it is simply what I have discovered on how things works.
I’ll only present a subset of the routines available (see the header files for QuickTime
2.0 which appear in the August Developer CD for more details), and all examples will
be based on what I’ve found in snooping around (so if I say that this parameter is zero,
that means that I’ve always seen this parameter as zero, not that it has to be - but
unless you like rebooting, you might want to leave it as zero). Also, I will attempt to
avoid as much “music theory” as possible, since not only are there good books on this
already, my knowledge is weak in that area, and I wouldn’t want to provide misleading
information. This will be in Pascal, and I’ll simplify the header file so we don’t have
to include dozens of other files (because QuickTime wants Aliases which wants
AppleTalk which wants, well, you get the idea). First, however, let’s look at a quick bit
of pseudo-code and see what it is we are going to do.
Overview
In order to play music, we need two important pieces of information - what notes
to play, and what instruments to play them on. This first part is the body of the tune,
while the second is what is called the header of the tune. In QuickTime, the tune
header, along with some additional information, is stored in the media handler
information (in the resource fork), while the tune body is stored in the actual data (on
the data fork). For this article, we will store both in a single resource, starting with
what the media handler information would be (as defined in MusicDescription record),
with the tune body appended onto the end.
Here, then, are the basic steps we will use to play music:
• Create a tune player component
• Feed the music header the header from our resource
• Tell it to start playing the body from our resource
• Wait until it finishes
• Make sure to tell it to stop playing
• Dispose and clean up.
But before we get to the code, let’s look how the music is stored (this is
important, so don’t skip ahead).
Storage of Musical Notes
Music is stored as a series of commands. Each command usually takes one
longint, but can take two or more. Examples of these commands are to play a given note
on a given instrument at a given pitch and given volume for a given duration, or to have
a given instrument wait a given duration. And thanks to the “Time” part of QuickTime,
multiple instruments can all be synched together, or their tempo can just as easily be
changed (but for you QuickTime junkies, I will not be getting into time bases).
These commands are similar to MIDI commands, if you are familiar with them. If
you aren’t, by the end of this section you’ll know that MIDI commands are similar to
QuickTime music commands. These commands are tagged with what the command is in
the high three or four bits, with the remaining bits (or following long word or words)
providing the parameters. Note that all commands are multiples of four bytes long, so
you can easily scan them as an array of LongInts.
Before we get to the commands themselves, we need to look at some of the
parameters first. Almost all commands require a integer parameter to specify which
instrument the command affects. An instrument is just that - a single instrument.
QuickTime provides 30 some odd instruments to choose from. You can have more than
one instrument playing in a given song (so you can have “Dueling -insert your
favorite instrument here-”). Also, a single instrument can play more than one note at
a time (being able to play a chord). Before playing the song, you tell the tune player
component how many instruments there are and what they are, but we’ll get into this
later.
Other parameters are fairly self explanatory.
Volume (also called velocity, because it refers to how hard you strike the key on
a keyboard), ranges from 0 (silent) to 63.
Duration is specified in units that are specific to the tune component (in our
examples we use 1/600ths of a second). Warning, some music theory follows: Based
on the default time units, and assuming 4/4 time (which means that a quarter note is
1/2 second long), below is a quick table of duration values and the length of notes they
produce:
Units at 600/secondNote produced
75 sixteenth note
150 eight note
300 quarter note
600 half note
1200 whole note
Pitch, which ranges from 0 to 127, corresponds to the same values MIDI uses.
Pitch ranges from C five octaves below middle C (0) to G five octaves above middle C
(127). Middle C has the value of 60. A complete table of these values can be found on
page 2-43 of the recently published IM:Sound. While it is possible to play what is
called “microtonal values”, which can be just about any pitch (they are represented
with fixed point numbers), this is done via a different, much less convenient,